#! /usr/bin/env python 
#coding=utf-8
import wx,time
from Load import *

reload(sys)
sys.setdefaultencoding('utf8')

FRAME_W = 600
FRAME_H = 500

BUTTON_W = 60
BUTTON_H = 25

#the bg color
#backcolourR = 210
#backcolourG = 210
#backcolourB = 210

backcolourR = 100
backcolourG = 210
backcolourB = 100

# File Menu Selections
ID_SAVE     = 101
ID_LOAD     = 102
ID_CMDFILE  = 103
ID_TESTCASE = 104
ID_EXIT     = 109
ID_ABOUT    = 110

class MyFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, wx.ID_ANY, 'AutoSystem', size=(FRAME_W,FRAME_H))
        self.SetPosition((wx.DisplaySize()[0]/2 -FRAME_W/2,wx.DisplaySize()[1]/2 - FRAME_H/2))
        self.SetMaxSize(wx.Size(FRAME_W, FRAME_H))
        self.SetMinSize(wx.Size(FRAME_W, FRAME_H))
        self.SetBackgroundColour(wx.Colour(backcolourR, backcolourG, backcolourB))
        self.jzcl1  = Load('jzcl1.txt')
        self.jzcl2  = Load('jzcl2.txt')
        self.psdkqk = LoadSimple('psdkqk.txt')
        self.swkrqx = Load('swkrqx.txt')
        self.xsdkdkqk = Load('xsdkdkqk.txt')
        self.xsdkjk = Load('xsdkjk.txt')
        self.yhddkqk  = Load('yhddkqk.txt')
        self.yhdjk  = Load('yhdjk.txt')
        self.createMenu()
        self.createControl()
        self.doLayout()
        self.bindEVT()
        self.data = {}
        self.LastChannel = self.Channel.GetValue().strip()
        self.LastFlush   = self.Flush.GetValue().strip()
        self.LastHole    = self.Hole.GetValue().strip()
        self.LastMachine = self.Machine.GetValue().strip()
        

    def createMenu(self):
        fileMenu = wx.Menu()
        # Append( UNIQUE_ID, Menu Title, Status Bar Text )
        fileMenu.Append(ID_CMDFILE,"&Open"," Open file")
        fileMenu.Append(ID_TESTCASE,"&Load File"," Load file") 
        fileMenu.AppendSeparator()
        fileMenu.Append(ID_LOAD, "&Load Settings", " Load settings from file")
        fileMenu.Append(ID_SAVE, "&Save Settings", " Save settings to file")
        fileMenu.AppendSeparator()
        fileMenu.Append(ID_EXIT, "&Exit", " Terminate the program")
        
        aboutMenu = wx.Menu()
        aboutMenu.Append(ID_ABOUT, '&About', 'About')
        # Creating the menubar
        menuBar = wx.MenuBar()
        menuBar.Append(fileMenu, '&File')
        menuBar.Append(aboutMenu, '&About')
        self.SetMenuBar(menuBar)

    def createControl(self):
        #title
        self.TitlePanel = wx.Panel(self)
        self.LabelTitle = wx.StaticText(self.TitlePanel, -1, u'SDIC  大峡水电站水位运行实时计算系统')
        myfont = wx.Font(20, wx.SWISS, wx.ITALIC, wx.BOLD)
        self.LabelTitle.SetFont(myfont)

        #head
        myfont = wx.Font(10, wx.SWISS, wx.ITALIC, wx.BOLD)
        self.HeadPanel = wx.Panel(self)
        s = time.strftime('%Y-%m-%d',time.localtime(time.time()))
        self.Date = wx.StaticText(self.HeadPanel, -1, u'日期:%s'%s)
        self.Date.SetFont(myfont)
        
        #input panel
        self.EditPanel = wx.Panel(self)
        labelfont = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD)
        #common varial
        self.HLabel = wx.StaticText(self.EditPanel, -1, u'上游水位(米):')
        self.Hedit = wx.TextCtrl(self.EditPanel,-1, '', size = (5,5), style = wx.TE_PROCESS_ENTER)
        self.LLabel = wx.StaticText(self.EditPanel, -1, u'下游水位(米):')
        self.Ledit = wx.TextCtrl(self.EditPanel,-1, '', size = (5,5), style = wx.TE_PROCESS_ENTER)
        self.TLabel = wx.StaticText(self.EditPanel, -1, u'目标水位(米):')
        self.Tedit = wx.TextCtrl(self.EditPanel,-1, '', size = (5,5), style = wx.TE_PROCESS_ENTER)
        self.HLabel.SetFont(labelfont)
        self.LLabel.SetFont(labelfont)
        self.TLabel.SetFont(labelfont)
        #machine
        self.machinelabel = wx.StaticText(self.EditPanel, -1, u'机组:')
        self.machinelabel.SetFont(labelfont)
        self.machineoptions = [u'0#机组',u'1#机组',u'2#机组',u'3#机组',u'4#机组']
        self.Machine = wx.ComboBox(self.EditPanel, choices=self.machineoptions, style = wx.CB_READONLY|wx.CB_DROPDOWN)
        self.Machine.SetSelection(0)
        self.mlabel1 = wx.StaticText(self.EditPanel, -1, u'水头(米):')
        self.mlabel1.SetFont(labelfont)
        self.medit1 = wx.TextCtrl(self.EditPanel,-1, '', size = (5,5), style = wx.TE_PROCESS_ENTER)
        self.mlabel2 = wx.StaticText(self.EditPanel, -1, u'出力(兆瓦):')
        self.mlabel2.SetFont(labelfont)
        self.medit2 = wx.TextCtrl(self.EditPanel,-1, '', size = (5,5), style = wx.TE_PROCESS_ENTER)

        #Chanel
        self.channeloptions = [u'溢洪道左孔',u'溢洪道中孔',u'溢洪道右孔']
        self.Channel = wx.ComboBox(self.EditPanel, choices=self.channeloptions, style = wx.CB_READONLY|wx.CB_DROPDOWN)
        self.Channel.SetSelection(0)
        self.ChannelLabel = wx.StaticText(self.EditPanel, -1, u'溢洪道开度(米):')
        self.ChannelLabel.SetFont(labelfont)
        self.ChannelEdit = wx.TextCtrl(self.EditPanel,-1, '', size = (5,5), style = wx.TE_PROCESS_ENTER)
        #flush
        self.flushoptions = [u'泄水底孔1',u'泄水底孔2']
        self.Flush = wx.ComboBox(self.EditPanel, choices=self.flushoptions, style = wx.CB_READONLY|wx.CB_DROPDOWN)
        self.Flush.SetSelection(0)
        self.FlushLabel = wx.StaticText(self.EditPanel, -1, u'泄水底孔开度(米):')
        self.FlushEdit = wx.TextCtrl(self.EditPanel,-1, '', size = (5,5), style = wx.TE_PROCESS_ENTER)
        #self.FlushEdit = wx.lib.masked.NumCtrl(panel, pos = (20,20), fractionWidth = 2)
        self.FlushLabel.SetFont(labelfont)
        #Hole
        self.holeoptions = [u'排沙孔1',u'排沙孔2',u'排沙孔3',u'排沙孔4']
        self.Hole = wx.ComboBox(self.EditPanel, choices=self.holeoptions, style = wx.CB_READONLY|wx.CB_DROPDOWN)
        self.Hole.SetSelection(0)
        self.HoleLabel = wx.StaticText(self.EditPanel, -1, u'排沙孔水头(米):')
        self.HoleLabel.SetFont(labelfont)
        self.HoleEdit = wx.TextCtrl(self.EditPanel,-1, '', size = (5,5), style = wx.TE_PROCESS_ENTER)
        
        #btn panel
        self.BtnPanel = wx.Panel(self)
        self.OK = wx.Button(self.BtnPanel, label='OK')
        self.Cancel = wx.Button(self.BtnPanel, label = 'Cancel')

        #output panel
        self.OutPutPanel = wx.Panel(self)
        self.LabelOutput = wx.StaticText(self.OutPutPanel, -1, u'结果输出:')
        self.Result = wx.StaticText(self.OutPutPanel, -1, u'')
        normalfont = wx.Font(15, wx.NORMAL, wx.NORMAL, wx.NORMAL)
        self.Result.SetFont(normalfont)
        #self.EditOutput = wx.TextCtrl(self.OutPutPanel,-1, '', size = (5,5), style = wx.TE_PROCESS_ENTER)
        myfont = wx.Font(20, wx.SWISS, wx.ITALIC, wx.BOLD)
        self.LabelOutput.SetFont(myfont)
    
    def doLayout(self):
        separator = 10
        for control, x, y, w, h in \
            [
             (self.TitlePanel, 0, 20,  600, 70),
             (self.HeadPanel,  0, 80,  600, 30),
             (self.EditPanel,  0, 120, 600, 155),
             (self.OutPutPanel,5, 290, 500, 100),
             (self.BtnPanel,   5, 370, 500, 90),
             ]:
            control.SetDimensions(x=x, y=y, width=w, height=h)

        #title
        self.LabelTitle.SetDimensions(x=30, y= 10, width= 600, height= 70)
        self.Date.SetDimensions(x=400, y= 0, width= 500, height= 30)
        #edit panel
        myh = 20
        x_pos = 10
        l_w = 100
        for control, x, y, w, h in \
            [
             (self.HLabel, x_pos, 5, l_w, myh),
             (self.LLabel, x_pos, 35, l_w, myh),
             (self.TLabel, x_pos, 65, l_w, myh),
             (self.Hedit,  x_pos+l_w, 5, 100, myh),
             (self.Ledit,  x_pos+l_w, 35, 100, myh),
             (self.Tedit,  x_pos+l_w, 65, 100, myh),
             ]:
            control.SetDimensions(x=x, y=y, width=w, height=h)

        x_pos = 220
        l_w = 90
        for control, x, y, w, h in \
            [
             (self.Channel, x_pos, 5, l_w, myh),
             (self.Flush, x_pos, 35, l_w, myh),
             (self.Hole, x_pos, 65, l_w, myh),
             ]:
            control.SetDimensions(x=x, y=y, width=w, height=h)
            
        x_pos = 330
        l_w = 140
        for control, x, y, w, h in \
            [
             (self.ChannelLabel,x_pos, 5, l_w, myh),
             (self.FlushLabel,  x_pos, 35,l_w, myh),
             (self.HoleLabel,   x_pos, 65,l_w, myh),
             (self.ChannelEdit, x_pos+l_w, 5, 100, myh),
             (self.FlushEdit,   x_pos+l_w, 35, 100, myh),
             (self.HoleEdit,    x_pos+l_w, 65, 100, myh),
             ]:
            control.SetDimensions(x=x, y=y, width=w, height=h)

        #机组
        x_pos = 35
        y_pos = 130
        for control, x, y, w, h in \
            [
             (self.machinelabel,x_pos, y_pos, 50, myh),
             (self.Machine,  x_pos+50, y_pos,70, myh),
             (self.mlabel1,   180, y_pos,70, myh),
             (self.medit1, 250, y_pos, 80, myh),
             (self.mlabel2,   360, y_pos, 90, myh),
             (self.medit2,    450, y_pos, 80, myh),
             ]:
            control.SetDimensions(x=x, y=y, width=w, height=h)
            
        self.LabelOutput.SetDimensions(x=35, y=10,width=180,height=30)
        self.Result.SetDimensions(x=200, y=10,width=100,height=30)

        self.OK.SetDimensions(x = 300,y=10,width=BUTTON_W,height=BUTTON_H)
        self.Cancel.SetDimensions(x = 310+BUTTON_W,y=10,width=BUTTON_W,height=BUTTON_H)
            
    def bindEVT(self):
        wx.EVT_MENU(self, ID_EXIT, self.OnClose)
        wx.EVT_MENU(self, ID_ABOUT, self.OnAbout)
        #listen the key:enter
        #self.EditWater.Bind(wx.EVT_TEXT_ENTER, self.OnWater)
        #self.EditOut.Bind(wx.EVT_TEXT_ENTER, self.OnOK)

        #combox
        self.Channel.Bind(wx.EVT_COMBOBOX, self.OnChannel)
        self.Flush.Bind(wx.EVT_COMBOBOX, self.OnFlush)
        self.Hole.Bind(wx.EVT_COMBOBOX, self.OnHole)
        self.Machine.Bind(wx.EVT_COMBOBOX, self.OnMachine)

        self.FlushEdit.Bind(wx.EVT_TEXT, self.onAction)

        for control, evt, handler in \
        [(self.OK, wx.EVT_BUTTON, self.OnOK),
         (self.Cancel, wx.EVT_BUTTON, self.OnClose),
         ]:
            control.Bind(evt, handler)

    def onAction(self, e):
        """
            check for numeric entry and limit to 2 decimals
            accepted result is in self.value
        """
        '''
        raw_value = self.FlushEdit.GetValue().strip()
        # numeric check
        if all(x in '0123456789.+-' for x in raw_value):
            # convert to float and limit to 2 decimals
            return True
        else:
            wx.MessageBox(u'请输入有效数字','无效值',wx.OK)
        '''
        pass
                      
    def OnChannel(self, e):
        value = self.ChannelEdit.Value.strip()
        ret = self.CheckValid(value)
        if not ret:
            self.Channel.SetSelection(self.channeloptions.index(self.LastChannel))
            self.ChannelEdit.Value = ''
            return
        key   = self.LastChannel
        self.LastChannel = self.Channel.GetValue().strip()
        if value == '':
            value = None
        self.data[key] = value

        #clean
        self.ChannelEdit.Value = ''

    def OnFlush(self, e):
        value = self.FlushEdit.Value.strip()
        ret = self.CheckValid(value)
        if not ret:
            self.Flush.SetSelection(self.flushoptions.index(self.LastFlush))
            self.FlushEdit.Value = ''
            return
        key   = self.LastFlush
        self.LastFlush = self.Flush.GetValue().strip()
        if value == '':
            value = None
        self.data[key] = value

        #clean
        self.FlushEdit.Value = ''

    def OnHole(self, e):
        value = self.HoleEdit.Value.strip()
        ret = self.CheckValid(value)
        if not ret:
            self.Hole.SetSelection(self.holeoptions.index(self.LastHole))
            self.HoleEdit.Value = ''
            return
        key   = self.LastHole
        self.LastHole = self.Channel.GetValue().strip()
        if value == '':
            value = None
        self.data[key] = value

        #clean
        self.HoleEdit.Value = ''

    def OnMachine(self, e):
        key   = self.LastMachine
        value1 = self.medit1.Value.strip()
        value2 = self.medit2.Value.strip()
        ret = self.CheckValid(value1) and self.CheckValid(value2)
        if not ret:
            self.Machine.SetSelection(self.machineoptions.index(self.LastMachine))
            self.medit1.Value = ''
            self.medit2.Value = ''
            return
        key = self.LastMachine
        self.LastMachine = self.Machine.GetValue().strip()
        if value1 == '':
            value1 = None
        if value2 == '':
            value2 = None
        self.data[key] = (value1,value2)
        
        #clean
        self.medit1.Value = ''
        self.medit2.Value = ''
    
    def OnAbout(self, e):
        wx.MessageBox('programmer:chenbin\nQQ:327507656','About',wx.OK)
        
    def OnClose(self, e):
        self.Close(True)
        self.DestroyChildren()
        self.Destroy()

    def PickData(self):
        #产生一个虚拟切换事件，以达到拾取所有数据
        self.OnChannel(None)
        self.OnFlush(None)
        self.OnHole(None)
        self.OnMachine(None)
        
    def OnOK(self, e):
        #下拉列表切换时，收集下拉列表最后一个值
        self.PickData()

        for key in self.data:
            value = self.data.get(key)
            if value:
                mylog.info('key:%s,value:%s'%(key,value))

        #计算并给出结果
        ret = self.CalQ()
        if not ret:
            mylog.error('Cal Q error!')
            return

        ret = self.CalW()
        if not ret:
            mylog.error('Cal W error!')
            return

        ret = self.CalP()
        if not ret:
            mylog.error('Cal P error!')
            return

        ret = self.CalM()
        if not ret:
            mylog.error('Cal M error!')
            return

        ret = self.CalX()
        if not ret:
            mylog.error('Cal X error!')
            return

        W,T = self.CalAll()
        mylog.info('W:%d,T:%d'%(W,T))
        T = int(T)
        h = T/3600
        m = (T-h*3600)/60
        s = (T-h*3600-m*60)
        result = u'1.当前流量W:%d\n2.还需%d时%d分%d秒到达目标水位'%(W,h,m,s)
        
        self.Result.SetLabel(result)
        #清空所有edit
        self.ClearAllEdit()

    def ClearAllEdit(self):
        #清空数据字典
        self.data.clear()
        #清空控件
        self.Hedit.Value = ''
        self.Ledit.Value = ''
        self.Tedit.Value = ''
        self.FlushEdit.Value = ''
        self.HoleEdit.Value = ''
        self.ChannelEdit.Value = ''
        self.medit1.Value = ''
        self.medit2.Value = ''
        
        self.Flush.SetSelection(0)
        self.Hole.SetSelection(0)
        self.Channel.SetSelection(0)
        self.Machine.SetSelection(0)

        
    def CalAll(self):
        #Q
        Q = self.Q[0] - self.Q[1]
        if Q<0:
            Q = -Q

        #w
        W = 0
        for item in self.W:
            W += item

        for item in self.P:
            W += item

        for item in self.M:
            W += item

        for item in self.X:
            W += item

        mylog.info('W:%d,Q:%d'%(W,Q))
        if Q ==0 or W == 0:
            T = 0
        else:
            T = Q/W
            mylog.info('T:%d'%T)
        return (W,T)
    
    def CalQ(self):
        #查swkrqx,获取Q1
        value = self.Hedit.Value.strip()
        mylog.info('Q:value=%s'%(value))
        if value == '':
            #没有输入
            Q1 = 0
        else:
            try:
                value = float(value)
            except:
                wx.MessageBox('Error:Invalid Number:%s'%value,'InvalidInput',wx.OK)
                self.Hedit.Value = ''
                return False
        x = str(value).split('.')[1][0]
        y = str(value).split('.')[0]
        mylog.info('x:%s,y:%s'%(x,y))
        Q1 = self.swkrqx.get((int(x)*factor,int(y)*factor))
        if not Q1:
            mylog.error('Error:Input not find in dictionary!')
            return False
        mylog.info('Q1 = %1f'%Q1)
        #目标水位
        value = self.Tedit.Value.strip()
        if value == '':
            Q2 = 0
        else:
            try:
                value = float(value)
            except:
                wx.MessageBox('Error:Invalid Number:%s'%value,'InvalidInput',wx.OK)
                self.Tedit.Value = ''
                return False
        x = str(value).split('.')[1][0]
        y = y = str(value).split('.')[0]
        Q2 = self.swkrqx.get((int(x)*factor,int(y)*factor))
        if not Q2:
            mylog.error('Error:Input not find in dictionary')
            return False
        mylog.info('Q2 = %f'%Q2)
        self.Q = []
        self.Q.append(Q1)
        self.Q.append(Q2)
        return True
    
    def CalW(self):
        #get 机组
        #debug
        W = []
        i = 0
        for item in self.machineoptions:
            if i == 0:
                tempdic = self.jzcl1
            else:
                tempdic = self.jzcl2
                
            data = self.data.get(item)
            if not data:
                #说明该机组没有输入，数据字典里没有
                mylog.info('W[%d] no input'%(i))
                W.append(0)
                continue

            x, y = data
            x = int(float(x)*factor)
            y = int(float(y)*factor)
            mylog.info('W[i]:x=%d,y=%d'%(x,y))
            value = tempdic.get((x,y))
            #未找到
            if not value:
                wx.MessageBox('Value in %s not find in dictionary!'%str(self.data.get(item)),'InvalidInput',wx.OK)
                return False
            else:
                W.append(value)
            mylog.info('W[%d]:%f'%(i,W[i]))
            i += 1
        mylog.info('Len(W):%d'%len(W))
        self.W = W
        return True
    
    def CalP(self):
        #排沙孔计算
        self.P = []
        i = 0
        for item in self.holeoptions:
            x = self.data.get(item)
            if not x:
                #数据区没有输入，取默认0
                self.P.append(0)
                i += 1
                continue
            value = self.psdkqk.get(int(float(x)*factor))
            if not value:
                wx.MessageBox('Value in %s not find in dictionary!'%str(self.data.get(item)),'InvalidInput',wx.OK)
                value = 0
            self.P.append(value)
            mylog.info('P[%d]:%f'%(i,self.P[i]))
            i += 1
        mylog.info('Len(P):%d'%len(self.P))
        return True

    def CalM(self):
        #溢洪道
        #水头>=15在全表里查
        self.M = []
        i = 0
        for item in self.channeloptions:
            x = self.data.get(item)
            if not x:
                #数据区没值
                self.M.append(0)
                i += 1
                continue
            if float(x)>= 15:
                dic = self.yhddkqk
            else:
                dic = self.yhdjk
            x = int(float(x)*factor)
            y = int(float(self.Hedit.Value)*factor)
            value = dic.get((x,y))
            if not value:
                wx.MessageBox('Not find in dictionary!','InvalidInput',wx.OK)
                return False
            self.M.append(value)
            mylog.info('M[%d]:%f'%(i,self.M[i]))
            i +=1
        mylog.info('Len(M):%d'%len(self.M))
        return True
    
    def CalX(self):
        #泄水孔
        self.X = []
        i = 0
        for item in self.flushoptions:
            x = self.data.get(item)
            if not x:
                self.X.append(0)
                continue
            else:
                value = self.CalFlush(float(x))
                if not value:
                    wx.MessageBox('Not find in dictionary!','InvalidInput',wx.OK)
                    return False
                else:
                    self.X.append(value)
            mylog.info('X[%d]:%f'%(i,self.X[i]))
            i += 1
        mylog.info('Len(X):%d'%len(self.X))
        return True
    
    def CalFlush(self, data):
        if data < 8:
            #局开
            x = int(data*factor)
            y = int(float(self.Hedit.Value)*factor)
            mylog.info('Data:%f,x=%d,y=%d'%(data,x,y))
            value = self.xsdkjk.get((x,y))
        else:
            #全开
            x = int(str(data).split('.')[1][0])
            y = int(str(data).split('.')[0])
            mylog.info('Data:%f,x=%d,y=%d'%(data,x,y))
            value = self.xsdkdkqk.get((x,y))
        mylog.info('Flush value:%f'%value)
        return value
        
    def CheckValid(self,s):
        if s == '':
            s = '0'
        try:
            i = float(s)
            return True
        except:
            wx.MessageBox('Error:Invalid Number:%s'%s,'InvalidInput',wx.OK)
            return False
        

class MyApp(wx.App):
    def OnInit(self):
        self._frame = MyFrame(None)
        self._frame.Show(True)
        self.SetTopWindow(self._frame)
        return True

if __name__ == '__main__':
    app = MyApp()
    app.MainLoop()
        
